import { createElement, HTMLAttributes, useEffect, useState, type FC } from 'react';
import classNames from 'classnames';
import { css, jsx, SerializedStyles } from '@emotion/react';
import { messageDefaultProps } from './defaultProps';
import type { MessageOptions } from './type';
import MessageHeader from './MessageHeader';
import MessageList from './MessageList';
import MessageItem from './MessageItem';
import MessageContent from './MessageContent';
import { Transition, transitionDefault } from '../common';

export interface MessageProps extends MessageOptions, Omit<HTMLAttributes<HTMLDivElement>, 'color'> {}

interface MessageInterface extends FC<MessageProps> {
  Header: typeof MessageHeader;
  Content: typeof MessageContent;
  List: typeof MessageList;
  Item: typeof MessageItem;
}

const Message: MessageInterface = (props) => {
  const {
    className,
    icon,
    hidden,
    visible,
    aligned,
    floating,
    compact,
    attached,
    type,
    close,
    color,
    size,
    onClosed,
    transition,
    children,
    forwardedRef,
    ...messageProps
  } = props;

  const [isHidden, setIsHidden] = useState(hidden);
  const [style, setStyle] = useState<SerializedStyles>();
  const [CssTransition, setCssTransition] = useState<string>();
  const [_transition, set_transition] = useState<Transition>(transitionDefault);

  useEffect(() => {
    if (typeof transition === 'string') {
      set_transition({ ..._transition, animation: transition });
    } else {
      set_transition({ ..._transition, ...transition });
    }
  }, [transition]);

  const handleClosed = (e: MouseEvent) => {
    e.preventDefault();
    setTimeout(() => {
      setCssTransition(`animating transition out ${_transition.animation}`);
      setStyle(
        css`
          display: ${typeof _transition.displayType === 'boolean' ? 'block' : _transition.displayType} !important;
          animation-duration: ${_transition.duration}ms;
        `,
      );
      if (_transition.skipInlineHidden) {
        setTimeout(() => {
          setCssTransition('transition');
          setStyle(undefined);
          setIsHidden(true);
          if (onClosed !== undefined) {
            onClosed(e);
          }
        }, Number(_transition.duration));
      }
    }, Number(_transition.interval));
  };

  return jsx(
    'div',
    {
      ref: forwardedRef,
      className: classNames(
        'ui',
        { icon, hidden: isHidden, visible, floating, compact },
        aligned,
        { aligned },
        attached,
        { attached },
        type,
        color,
        size,
        'message',
        CssTransition,
        className,
      ),
      css: style,
      ...messageProps,
    },
    [close && createElement('i', { key: 'close', className: 'close icon', onClick: handleClosed }), children],
  );
};

Message.displayName = 'Message';
Message.defaultProps = messageDefaultProps;

Message.Header = MessageHeader;
Message.Content = MessageContent;
Message.List = MessageList;
Message.Item = MessageItem;

export default Message;
